#include <bits/stdc++.h>

using namespace std;

inline void chmax(int &a, int b) {
  if (a < b)
    a = b;
}

int main() {

  int n; // 孩子数量
  cin >> n;

  vector<int> a(n); // 存储每个孩子的糖果数
  for (int i = 0; i < n; i++)
    cin >> a[i]; // 读取每个孩子的糖果数

  // 第二步：可行性检查和差额计算
  {
    int sum = 0;
    for (int i = 0; i < n; i++)
      sum += a[i]; // 计算总糖果数

    // 检查可行性：总糖果数必须能被n整除
    if (sum % n) {
      puts("-1"); // 无解情况
      return 0;
    }

    // 计算平均值并转换为差额数组
    sum /= n; // 每个孩子应该拥有的糖果数
    for (int i = 0; i < n; i++)
      a[i] -= sum; // a[i]现在表示每个孩子的差额（正数表示多余，负数表示缺少）
  }

  // 第三步：预处理所有子集的和
  int n2 = 1 << n;      // 子集总数：2^n（使用位运算表示子集）
  vector<int> sums(n2); // sums[s]表示子集s的差额和

  // 计算每个子集的和
  for (int s = 0; s < n2; s++) {
    for (int i = 0; i < n; i++) {
      if (s >> i & 1)
        sums[s] += a[i]; // 如果第i位为1，表示包含孩子i
    }
  }

  // 第四步：动态规划计算最大子集划分数
  // dp[s]表示在集合s中能划分出的和为0的子集的最大数量
  vector<int> dp(n2);
  for (int s = 0; s < n2; s++) {
    // 如果当前子集的和为0，可以作为一个独立的子集
    if (sums[s] == 0)
      dp[s]++;

    // 状态转移：尝试向当前集合添加新元素
    for (int i = 0; i < n; i++) {
      if (~s >> i & 1) {       // ~s >> i & 1 检查第i位是否为0（即i不在集合s中）
        chmax(dp[s | 1 << i], dp[s]); // 更新包含元素i的新集合的最大划分数
      }
    }
  }

  // 第五步：路径重建，找到具体的子集划分方案
  vector<int> p; // 存储划分后的顶点顺序（孩子编号）
  {
    int s = n2 - 1; // 全集：所有n个孩子（二进制表示为111...1）
    while (s) {
      // 如果当前集合和为0，说明这是一个完整的子集
      if (sums[s] == 0)
        dp[s]--;

      // 回溯找到划分方案
      for (int i = 0; i < n; i++) {
        if (s >> i & 1) { // 遍历集合s中的每个元素
          // 如果去掉元素i后划分数不变，说明i属于当前子集
          if (dp[s] == dp[s ^ 1 << i]) {
            s ^= 1 << i;    // 从集合中移除元素i（异或操作翻转第i位）
            p.push_back(i); // 记录顶点顺序
            break;          // 找到一个就跳出循环
          }
        }
      }
    }
  }

  // 第六步：生成操作序列
  vector<tuple<int, int, int>> lefts, rights; // 分别存储向左和向右的传输操作
  {
    int sum = 0; // 累计当前子集的差额
    // 按照划分顺序处理每个子集（链式传输）
    for (int i = 0; i < n - 1; i++) {
      sum += a[p[i]]; // 累计当前子集的差额

      // 正差额：需要向右传输糖果（从当前顶点传给下一个顶点）
      if (sum > 0)
        rights.emplace_back(p[i], p[i + 1], sum); // (源点, 目标点, 传输量)

      // 负差额：需要向左传输糖果（从下一个顶点传给当前顶点）
      if (sum < 0)
        lefts.emplace_back(p[i + 1], p[i], -sum); // 注意传输量为正数
    }
  }

  // 第七步：合并操作序列并输出结果
  auto ans = rights;                   // 先处理所有向右传输的操作
  reverse(lefts.begin(), lefts.end()); // 反转左传输序列（为了处理顺序）
  ans.insert(ans.end(), lefts.begin(), lefts.end()); // 合并左右传输操作

  // 输出结果
  cout << ans.size() << '\n'; // 输出最小操作次数
  for (auto [s, t, c] : ans)
    cout << s + 1 << ' ' << t + 1 << ' ' << c
         << '\n'; // 输出具体操作（注意编号从1开始）

  return 0;
}